/*
 * 上海远境文化传媒有限公司 版权所有
 */
package controllers.api.v1.auth;

import cache.CacheHelper;
import ext.Func;
import ext.auth.ActiveNav;
import ext.auth.AppUserInfo;
import ext.auth.CheckFunc;
import ext.auth.CheckUserRole;
import ext.auth.SkipAuthCheck;
import ext.auth.SkipCheckLicense;
import ext.auth.SkipCheckUserStatus;
import ext.auth.UserAuthHelper;
import ext.play.ResponseUtility;
import facade.AppContext;
import facade.base.AdminUserFacade;
import facade.base.CorpFacade;
import facade.open.BaseJsonAPI;
import facade.vo.base.RoleBusinessVO;
import helper.GlobalConfig;
import models.base.*;
import models.enums.ClientType;
import models.enums.OpenIdSource;
import models.enums.UserRole;
import org.apache.commons.lang.StringUtils;
import play.Logger;
import play.Play;
import play.libs.Codec;
import play.mvc.Before;
import play.mvc.Finally;
import util.play.RequestUtility;
import util.play.TimeTracker;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Api认证检查.
 */
public class ApiAuth extends BaseJsonAPI {

    @Before
    public static void beforeAuthRequest() {
        //TimeTracker.startTrack();
    }

    /**
     * 检查是否已经OAuth认证过，如果没有，则调用认证.
     *
     * @throws Throwable
     */
    @Before(unless = {"login", "logout", "fail", "validate", "validation", "authenticate", "captcha"})
    public static void filter() throws Throwable {

        Logger.info("TLQ193871: [ApiAuth]: Filter for URL -> %s", request.url);

//        // 设置ApiPlatform
//        OpenIdSource apiPlatform = UserAuthHelper.getCurrentApiPlatform();
//
//        AppContext.setApiPlatform(apiPlatform);
//
//        ClientType clientType = UserAuthHelper.getCurrentClientType();
//        AppContext.setClientType(clientType);

        if (skipAuthCheck()) {
            Logger.info("LOG02960:[ApiAuth]: Skip the Auth Check.");
            return;
        }

        // 按x-hyshi-session读取sessionId
        String sessionId = RequestUtility.getHeaderIgnoreCase(GlobalConfig.API_HEADER_TOKEN);
        Logger.info("SessionId 111 : %s" , sessionId);
//        if(StringUtils.isBlank(sessionId)) {
//            //sessionId = "eyJhbGciOiJIUzUxMiIsInppcCI6IkRFRiJ9.eNqqViouTVKyUgqKyC0uyg42D4xMN49IiTAOi8h2DcpW0lFKLE0BSgc4BgeH-we5AAVSKwqUrAxNDc1MjYwtzA1rAQAAAP__.zPaPkYoGX1RK6X7oPR_jhtEXQgALMGT84js0Qxv_PiB55G5IqRIodzsJHg3eMzCsaCdYD9084aM6g62-WW6DZA";
//
//            renderFailMessage(401, "需要登录");
//        }
        Logger.info("LOG00000: sessionId = " + sessionId);
        AdminUser user = getUserFromRequest(sessionId);
        Logger.debug("LOG103881: Secure.LoginUser : %s", user);

        if (user == null) {
            // 非法用户
            Logger.warn("LOG00440: user is null, 不能进行操作");
            renderFailMessage(401, "需要登录");
            return;
        }

        if (!checkHasUserRole(user)) {
            Logger.info("[ApiAuth]: No Permissions.");
            renderFailMessage(403, "无权限使用该功能");
        }


//
//        if (!skipCheckUserStatus() && !user.isActive()) {
//            if (user.corp != null && StringUtils.isBlank(user.email)) {
//                //forbidden("用户无公司");
//                Logger.info("TLQ561440: 用户无公司");
//            }
//            Logger.info("LOG018386: 用户没有激活：" + user);
//            renderFailMessage(401, "用户未激活");
//        }

    }

    private static void storeUserInfoToContext(AdminUser user) {
        if (user != null) {
            //user.setRoleSet( Role.loadRoles(user) );
            renderArgs.put("currentUser", user);
            AppContext.setUsr(user);
            if (user.corp != null) {
                //Corp corp = Corp.findById(user.corp.id); // TODO: 需要缓存
                AppContext.setCorp(user.corp);
                renderArgs.put("currentCorp", user.corp);

//                if (!checkCorpHasFunc(user.corp)) {
//                    notFound();
//                }

//                if (!skipCheckLicense()) {
//                    CorpFacade.processLicenseCheck(corp).onBack(() -> {
//                        // 不允许 GET 之外的操作
//                        response.status = 403;
//                        getApiResponse().code = 403;
//                        getApiResponse().message = "授权已过期";
//                        renderApiResponse();
//                    }).end();
//                }
            }
        }
    }


    @Finally
    public static void finallCleanup() {
        AppContext.cleanUp();
        ResponseUtility.setCorsHeaders();
    }

    /**
     * 尝试从Session中得到用户信息.
     */
    private static AdminUser getUserFromRequest(String sessionId) {
        AdminUser user = null;
        if (StringUtils.isBlank(sessionId)) return null;
        // 如果session被禁用
//        if (CacheHelper.exists(Codec.hexMD5(sessionId))) {
//            Logger.info("LOG03733: 已经注销sessionId, 不能使用： " + sessionId);
//            return null;
//        }

        sessionId = sessionId.replace("Basic ","").replace("basic ","");
        // 设置CSRF cookie
        //UserAuthHelper.setupCsrfCookie(sessionId);

        AppUserInfo wxAppUserInfo = UserAuthHelper.getWxAppUserInfoFromJwt(sessionId);

            // 检查CSRF
            /*
            if (!request.method.equals("GET") && !checkHasAnnotation(SkipCsrfCheck.class) ) {
                // 按x-hyshi-session读取sessionId
                String authenticityToken = RequestUtility.getHeaderIgnoreCase(HEADER_CSRF_KEY);

                String csrfKey = CacheHelper.getCache(UserAuthHelper.getCsrfCacheKey(sessionId), () -> Crypto.sign(UUID.randomUUID().toString()));
                Logger.info("TLQ338590: authenticityToken=%s, session=%s", authenticityToken, csrfKey);

                if (authenticityToken == null
                        || !authenticityToken.equals(csrfKey)) {

                    if (wxAppUserInfo != null && OpenIdSource.WXAPP != wxAppUserInfo.openIdSource) {
                        Logger.info("TLQ238840: wxAppUserInfo=%s", wxAppUserInfo);
                        renderFailMessage(403, "Bad authenticity token");
                    } else {
                        Logger.info("TLQ502020: csrf check authenticity. wxAppUserInfo=" + wxAppUserInfo);
                    }
                }
            }
            */

            Logger.debug("TLQ469970: wxAppUserInfo=%s", wxAppUserInfo);
            if (wxAppUserInfo != null && wxAppUserInfo.userId != null) {
                user = AdminUserFacade.getById(wxAppUserInfo.userId);
                if (user == null) {
                    Logger.info("[ApiAuth] user is null for sessionUserId=" + sessionId);
                    //CacheHelper.delete(sessionId);
                    renderFailMessage(401, "用户已经删除需要重新登录");
                    return null;
                }
                //CacheHelper.setCache(sessionId, wxAppUserInfo);
            }


        /*
        if (user == null) {
            // for test
            Logger.info("[ApiAuth] for test user is null");
            //if (Play.mode.isDev() && (request.domain != null && request.domain.contains("localhost"))) {
            if (Play.mode.isDev() && !Play.runingInTestMode()) {
                user = User.find("loginName=?1 and isAdmin=?2", "admin", Boolean.TRUE).first();
            }
        }
        */

        storeUserInfoToContext(user);

        Logger.debug("TLQ268173: [ApiAuth] user=%s", user);
        return user;
    }

    /**
     * 检查是否要跳过认证检查.
     *
     * @return 返回true表明跳过检查.
     */
    private static boolean skipAuthCheck() {
        boolean skipAuthCheck = checkHasAnnotation(SkipAuthCheck.class);
        Logger.debug("TLQ112571: SkipAuthCheck=%s", skipAuthCheck);
        return skipAuthCheck;
    }

    /**
     * 是否跳过用户状态的检查.
     *
     * @return 返回true表明跳过检查.
     */
    private static boolean skipCheckUserStatus() {
        boolean checkHasAnnotation = checkHasAnnotation(SkipCheckUserStatus.class);
        Logger.debug("TLQ112572: checkHasAnnotation=%s", checkHasAnnotation);
        return checkHasAnnotation;
    }

    private static boolean checkHasAnnotation(Class annoClass) {
        return getActionAnnotation(annoClass) != null ||
                getControllerInheritedAnnotation(annoClass) != null;
    }


    private static boolean skipCheckLicense() {
        return checkHasAnnotation(SkipCheckLicense.class);
    }


    /**
     * 检查是否有管理员权限.
     */
    private static boolean checkHasUserRole(AdminUser user) {
        if(user.isSuperAdmin || user.isDiySuperAdmin()) return true;
        boolean needCheckRole = false;
        CheckUserRole actionAnnotation = getActionAnnotation(CheckUserRole.class);
        CheckUserRole controllerInheritedAnnotation = getControllerInheritedAnnotation(CheckUserRole.class);
        if (actionAnnotation != null) {
            String[] roles = actionAnnotation.value();
            //if (!user.isAdmin()) {
                for (String role : roles) {
                    if (user.getRoleSet().contains(role)) {
                        return true;
                    }
                }
            //}
            needCheckRole = true;
        }
        if (controllerInheritedAnnotation != null) {
            String[] roles = controllerInheritedAnnotation.value();
            //if (!user.isAdmin()) {
                for (String role : roles) {
                    if (user.getRoleSet().contains(role)) {
                        return true;
                    }
                }
            //}
            needCheckRole = true;
        }
        return !needCheckRole || user.isAdmin();  // 用户没有对应权限
    }

    /**
     * 得到当前导航的设置.
     */
    private static String getActiveNavValue() {
        if (getActionAnnotation(ActiveNav.class) != null) {
            return getActionAnnotation(ActiveNav.class).value();
        }
        if (getControllerInheritedAnnotation(ActiveNav.class) != null) {
            return getControllerInheritedAnnotation(ActiveNav.class).value();
        }
        return null;
    }


    /**
     * 检查当前公司是否有指定功能授权.
     */
    private static boolean checkCorpHasFunc(Corp corp) {
        if (corp == null) {
            return true;
        }
        Func func = null;
        if (getControllerInheritedAnnotation(CheckFunc.class) != null) {
            func = getControllerInheritedAnnotation(CheckFunc.class).value();
        }
        if (getActionAnnotation(CheckFunc.class) != null) {
            func = getActionAnnotation(CheckFunc.class).value();
        }
        if (func != null && !corp.hasFunc(func)) {
            Logger.info("LOG02351: [ApiAuth]公司(id:%s, name:%s, licenseEdition:%s) 没有产品功能授权: %s",
                    corp.id, corp.name, corp.licenseEdition, func);
            return false;
        }
        return true;
    }

}
